package com.imooc.controller;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.google.gson.Gson;
import com.imooc.api.mq.RabbitMQSMS2Config;
import com.imooc.api.mq.RabbitMQSMSConfig;
import com.imooc.base.BaseInfoProperties;
import com.imooc.grace.result.GraceJSONResult;
import com.imooc.grace.result.ResponseStatusEnum;
import com.imooc.pojo.BO.RegisterLoginBO;
import com.imooc.pojo.MQ.SMSContentQO;
import com.imooc.pojo.Users;
import com.imooc.pojo.VO.UsersVO;
import com.imooc.service.UsersService;
import com.imooc.utils.GsonUtils;
import com.imooc.utils.IPUtil;
import com.imooc.utils.JWTUtils;
import com.imooc.utils.SMSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.UUID;

/**
 * app端一键注册登录
 */
@RestController
@RequestMapping("passport")
@Slf4j
public class PassportController extends BaseInfoProperties {

    @Autowired
    private SMSUtils smsUtils;
    @Autowired
    private UsersService usersService;
    @Autowired
    private JWTUtils jwtUtils;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送短信验证码
     */
    @PostMapping("getSMSCode")
    public GraceJSONResult getSMSCode(
            String mobile,
            HttpServletRequest request
    ) throws Exception {

        if (StringUtils.isBlank(mobile)) {
            return GraceJSONResult.errorMsg("手机号呢");
        }

        // 获得用户ip
        String userIp = IPUtil.getRequestIp((request));
        // 限制用户只能在60秒内获取一次验证码，限制代码在拦截器中 com.imooc.api.Config.InterceptorConfig
        redis.setnx60s(MOBILE_SMSCODE + ":" + userIp, mobile);

        String code = (int) ((Math.random() * 9 + 1) * 100000) + "";
//        smsUtils.sendSMS("15688463267", code);

        // 使用消息队列异步解耦发送短信
        SMSContentQO smsContentQO = new SMSContentQO();
        smsContentQO.setMobile(mobile);
        smsContentQO.setContent(code);

//        // 定义confirm回调
//        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
//            /**
//             * 回调函数
//             * @param correlationData 相关性数据
//             * @param ack 交换机是否成功接收消息，true：成功
//             * @param cause 失败的原因
//             */
//            @Override
//            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
//                log.info("      ===== 进入confirm =====       ");
//                log.info("correlationData:{}", correlationData);
//                if (ack) {
//                    log.info("交换机成功接收消息~ ~  {}", cause);
//                } else {
//                    log.info("交换机接收消息失败! !  {}", cause);
//                }
//            }
//        });
//
//        // 定义return回调
//        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
//            @Override
//            public void returnedMessage(ReturnedMessage returned) {
//                log.info("进入returnCallback");
//                log.info("returned:{}", returned);
//            }
//        });

//        // 消息属性处理的类对象（对当前需要的超时ttl进行参数属性的设置）
//        MessagePostProcessor processor = new MessagePostProcessor() {
//            @Override
//            public Message postProcessMessage(Message message) throws AmqpException {
//                message.getMessageProperties().setExpiration(String.valueOf(10 * 1000));
//                return message;
//            }
//        };

        rabbitTemplate.convertAndSend("", RabbitMQSMS2Config.SMS_QUEUE,
                GsonUtils.object2String(smsContentQO),
                message -> {
                    message.getMessageProperties().setExpiration(String.valueOf(10 * 1000));
                    return message;
                }, new CorrelationData(UUID.randomUUID().toString())); // new Gson().toJson(smsContentQO)

        log.info("验证码为：{}", code);
        // 把验证码存入到redis，用于会序的注册登录进行校验
        redis.set(MOBILE_SMSCODE + ":" + mobile, code, 30 * 60);

        return GraceJSONResult.ok();
    }

    /**
     * APP端手机一键注册登录
     */
    @PostMapping("login")
    public GraceJSONResult login(
            @Valid @RequestBody RegisterLoginBO registerLoginBO,
            HttpServletRequest request
    ) {
        String mobile = registerLoginBO.getMobile();
        String smsCode = registerLoginBO.getSmsCode();

        // 1. 从redis中获取验证码进行校验判断是否匹配
        String redisCode = redis.get(MOBILE_SMSCODE + ":" + mobile);
        if (StringUtils.isBlank(redisCode) || !redisCode.equals(smsCode)) {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.SMS_CODE_ERROR);
        }

        // 2. 根据mobile查询数据库，判断用户是否存在
        Users user = usersService.queryUserByMobile(mobile);
        if (user == null) {
            // 2.1 如果查询的用户为空，则表示没有注册过，进行注册
            user = usersService.createUser(mobile);
        }

        String jwt = jwtUtils.createToken(new Gson().toJson(user), 100000000L, TOKEN_USER_PREFIX); // 毫秒

        // 3. 用户登录注册以后，删除redis中的短信验证码
        redis.del(MOBILE_SMSCODE + ":" + mobile);

        // 4. 返回信息给前端
        UsersVO usersVO = new UsersVO();
        BeanUtils.copyProperties(user, usersVO);
        usersVO.setUserToken(jwt);

        return GraceJSONResult.ok(usersVO);
    }


    /**
     * APP端用户退出登录
     */
    @PostMapping("logout")
    public GraceJSONResult logout(
            @RequestParam String userId
    ) {
        // 后端只需清除用户的redisToken信息即可，使用JWTToken这个接口就没用了
        redis.del(REDIS_USER_TOKEN + ":" + userId);
        return GraceJSONResult.ok();
    }
}
